package com.gitee.dolt.utils;


import cn.hutool.core.collection.CollUtil;

import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * @author LYH
 */
public class CollUtils {
    /**
     * 计算map 初始容量
     *
     * @param size       已知数量
     * @param loadFactor 加载因子
     * @return map 初始容量
     */
    public static int initialCapacity(int size, float loadFactor) {
        return (int) (size / loadFactor + 1);
    }

    /**
     * 计算map 初始容量
     *
     * @param size 已知数量
     * @return map 初始容量
     */
    public static int initialCapacity(int size) {
        return initialCapacity(size, 0.75F);
    }

    /**
     * 将树平铺
     *
     * @param top             顶级节点
     * @param listChildrenFun 获取子节点的方式
     * @param <T>
     * @return
     */
    public static <T> List<T> flatTree(T top, Function<T, Collection<T>> listChildrenFun) {
        if (top == null) {
            return Collections.emptyList();
        }
        List<T> result = new ArrayList<>();
        result.add(top);
        Collection<T> children = listChildrenFun.apply(top);
        if (CollUtil.isNotEmpty(children)) {
            children.forEach(child -> result.addAll(flatTree(child, listChildrenFun)));
        }
        return result;
    }

    /**
     * 设置树结构
     *
     * @param top            顶级节点
     * @param parentGroup    parent分组
     * @param getGroupKeyFun 获取分组的key
     * @param setChildrenFun 设置子项
     * @param <T>
     * @param <M>
     */
    public static <T, M> void setTree(T top, Map<M, List<T>> parentGroup, Function<T, M> getGroupKeyFun, BiConsumer<T, List<T>> setChildrenFun) {
        if (top == null) {
            return;
        }
        List<T> children = parentGroup.get(getGroupKeyFun.apply(top));
        setChildrenFun.accept(top, children);
        if (CollUtil.isNotEmpty(children)) {
            children.forEach(child -> setTree(child, parentGroup, getGroupKeyFun, setChildrenFun));
        }
    }

    public static <T> void eachTree(T top, Function<T, Collection<T>> listChildrenFun, BiConsumer<T, T> handleFun) {
        if (top == null) {
            return;
        }
        Collection<T> children = listChildrenFun.apply(top);
        if (CollUtil.isNotEmpty(children)) {
            children.forEach(child -> {
                handleFun.accept(top, child);
                eachTree(child, listChildrenFun, handleFun);
            });
        }
    }

}
